#pragma once
#include <iostream>
#include "utility/index.hpp"
#include "request_access/index.hpp"
#include "data_access/index.hpp"
#include "components/index.hpp"
#include "actions.hpp"

using namespace std;
using namespace utility;

namespace components2 {
    class PurchaseOrder : public components::EntityRequest {
    public:
        COMPONENT_INSTANCE_FUNCTION(PurchaseOrder);

        PurchaseOrder();

        any UpdateStatus();

        any Insert2();

        any CancelReview();

        any GetSupply();

        any AddSupply();

    private:
        EntityData getSupplyOrder(EntityData &purchaseOrder);
        EntityData getSupplyOrder();

        vector<EntityData> getPurchaseSupply(const any &purchaseOrderId);

        entity_access::EntityType *supplyOrderEntity;
    };

    PurchaseOrder::PurchaseOrder() {
        SET_METHOD_ACTION(UpdateStatus);
        SET_METHOD_ACTION(Insert2);
        SET_METHOD_ACTION(CancelReview);
        SET_METHOD_ACTION(GetSupply);
        SET_METHOD_ACTION(AddSupply);
        supplyOrderEntity = entity_access::GetEntityType("SupplyOrder");
    }

    std::any PurchaseOrder::UpdateStatus() {
        EntityData dict = Request->RequestEntity.GetEntityData(Entity->Name);

        auto oldEntityData = SelectEntityByPrimaryKey(QueryRequest->PrimaryKeyValue);
        if (oldEntityData.Empty()) return Request->GetMessageMap("采购订单不存在");

        auto msg = CompareVersion(dict, oldEntityData);
        if (!msg.empty()) return Request->GetMessageMap(msg);

        int status = dict.GetInt("Status");
        bool isSyncSupply = oldEntityData.GetBool("IsSyncSupply");

        if (isSyncSupply && status == 2)components::EntityByComplexTypeOperation::GetComplexTypeEntityDataList(shared_from_this(), oldEntityData);

        bool blSucceed = true;
        try {
            DataBase->BeginTransaction();

            blSucceed = Actions::UpdateStatusAndReview(shared_from_this(), supplyOrderEntity, dict, 1);

            EntityData supplyOrder;
            if (blSucceed && isSyncSupply && status == 2) {
                supplyOrder = getSupplyOrder(oldEntityData);
                blSucceed = InsertEntity(supplyOrderEntity, supplyOrder);
                if (blSucceed) blSucceed = components::EntityByComplexTypeOperation::EditDeleteComplexType(shared_from_this(), supplyOrderEntity, supplyOrder, false);
            }

            if (blSucceed && isSyncSupply && status == 2) Actions::UpdateOrderCode(shared_from_this(), 2, supplyOrder.Get("SupplyOrderId"));

            if (blSucceed) DataBase->CommitTransaction();
            else DataBase->RollbackTransaction();
        } catch (const std::exception &e) {
            DataBase->RollbackTransaction();
             throw MessageException(e.what(),"");
        }

        return GetSucceedMap(blSucceed);
    }

    EntityData PurchaseOrder::getSupplyOrder(EntityData &purchaseOrder) {
        EntityData data;

        data["PurchaseOrderId"] = purchaseOrder["PurchaseOrderId"];
        data["SupplyDate"] = purchaseOrder["PurchaseDate"];
        data["Status"] = 2;
        data["Remark"] = "采购订单同步操作";
        data["CreateUser"] = purchaseOrder["CreateUser"];

        auto details = purchaseOrder.GetEntityDataList("Details");

        vector<EntityData> detailList;
        for (auto &d: details) {
            EntityData detail;
            detail["Num"] = d["Num"];
            detail["DisplayIndex"] = d["DisplayIndex"];
            detail["MaterialProductId"] = d["MaterialProductId"];
            detailList.emplace_back(detail);
        }

        data["Details"] = detailList;

        return data;
    }


    any PurchaseOrder::Insert2() {
        return Actions::Insert2(shared_from_this(), 1);
    }

    any PurchaseOrder::CancelReview() {
        Actions::SetCancelReviewEntityData(shared_from_this());
        return UpdateStatus();
    }

    vector<EntityData> PurchaseOrder::getPurchaseSupply(const any &purchaseOrderId) {
        auto parameters = make_shared<data_access::DataParameters>();
        parameters->Add("@PurchaseOrderId", purchaseOrderId);

        auto query = make_shared<data_access::Query>("v_PurchaseSupplyDetail");
        query->Select("PurchaseOrderId,ProductTypeName,MaterialProductId,MaterialProductName,Num PurchaseNum,SupplyNum,BalanceNum");
        query->Where("where PurchaseOrderId=@PurchaseOrderId and BalanceNum<>0", parameters);
        query->OrderBy("order by DisplayIndex");

        return SelectEntities(query);
    }

    any PurchaseOrder::GetSupply() {
        EntityData obj;
        obj["PurchaseOrderId"] = QueryRequest->PrimaryKeyValue;

        auto entityData = SelectEntityByPrimaryKey(QueryRequest->PrimaryKeyValue);
        if(entityData.Empty()) return Request->GetMessageMap("采购订单不存在");

        obj["RowVersion"]= entityData["RowVersion"];

        auto details = getPurchaseSupply(QueryRequest->PrimaryKeyValue);
        if (details.empty()) return Request->GetMessageMap("没有需供应的商品明细，请刷新页面！");
        obj["Details"] = details;

        return obj;
    }

    any PurchaseOrder::AddSupply() {
        auto dict = Request->RequestEntity.GetEntityData(Entity->Name);
        auto entityData = SelectEntityByPrimaryKey(QueryRequest->PrimaryKeyValue);
        if(entityData.Empty()) return Request->GetMessageMap("采购订单不存在");

        auto msg = CompareVersion(dict, entityData);
        if(!msg.empty()) return Request->GetMessageMap(msg);

        EntityData supplyOrder = getSupplyOrder();
        bool blSucceed = true;

        try {
            DataBase->BeginTransaction();

            blSucceed = InsertEntity(supplyOrderEntity, supplyOrder);
            if (blSucceed) blSucceed = components::EntityByComplexTypeOperation::EditDeleteComplexType(shared_from_this(), supplyOrderEntity, supplyOrder, false);

            if (blSucceed) {
                EntityData updateEntityData;
                updateEntityData["UpdateDate"] = DateTime();
                updateEntityData["UpdateUser"] = Request->OperationUser;

                blSucceed = UpdateEntityByPrimaryKey(QueryRequest->PrimaryKeyValue, updateEntityData);
            }
            if (blSucceed)Actions::UpdateOrderCode(shared_from_this(), 2, supplyOrder.Get("SupplyOrderId"));
            if (blSucceed) DataBase->CommitTransaction();
            else DataBase->RollbackTransaction();
        } catch (const std::exception &e) {
            DataBase->RollbackTransaction();
             throw MessageException(e.what(),"");
        }

        return GetSucceedMap(blSucceed);
    }

    EntityData PurchaseOrder::getSupplyOrder() {
        auto dict = Request->RequestEntity.GetEntityData(Entity->Name);
        EntityData data;

        data["PurchaseOrderId"] = dict["PurchaseOrderId"];
        data["SupplyDate"] = dict["SupplyDate"];
        data["Remark"] = dict["Remark"];
        data["CreateUser"] = Request->OperationUser;

        auto details = dict.GetEntityDataList("Details");

        vector<EntityData> detailList;
        for (auto &d: details) {
            auto num = d.GetFloat("Num");
            if (num != 0) {
                EntityData detail;
                detail["Num"] = d["Num"];
                detail["DisplayIndex"] = d["DisplayIndex"];
                detail["MaterialProductId"] = d["MaterialProductId"];
                detailList.emplace_back(detail);
            }
        }

        if (detailList.empty()) throw MessageException("商品明细供应数量不能都为0", "");

        data["Details"] = detailList;

        return data;
    }
}